package com.example.testdemo.pools;

import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.andengine.entity.modifier.PathModifier.Path;
import org.andengine.entity.sprite.Sprite;
import org.andengine.extension.tmx.TMXTile;

import android.util.Log;

import com.example.testdemo.ai.AStarSearch;

public class PathPools {

	public static interface IOnPathReadyListener {
		public void onPathReady(int pathType, Path path);
	}
	
	public static final int TARGET_RANDOM_GROUND = 1;
	public static final int TARGET_PLAYER = 2;

	public static class PathRequester {
		private Sprite mStart = null;
		private TMXTile mToTile = null;
		private List<Sprite> mWallList = null;
		private List<Sprite> mObstacleList = null;
		private int mPathTarget = TARGET_RANDOM_GROUND;
		private IOnPathReadyListener mListener;

		public PathRequester(Sprite sprite, TMXTile toTile,
		        List<Sprite> wallList, List<Sprite> obstacleList, int pathType,
		        IOnPathReadyListener listener) {
			mStart = sprite;
			mToTile = toTile;
			mWallList = wallList;
			mObstacleList = obstacleList;
			mPathTarget = pathType;
			mListener = listener;
		}
	}

	private static final String TAG = PathPools.class.getSimpleName();

	private static PathPools sPools;
	private ConcurrentLinkedQueue<PathRequester> mRequesterQueue = new ConcurrentLinkedQueue<PathPools.PathRequester>();
	private ConcurrentLinkedQueue<PathRequester> mHandlingQueue = new ConcurrentLinkedQueue<PathPools.PathRequester>();

	private PathPools() {
		mPathGenerator.setPriority(Thread.MIN_PRIORITY);
		mPathGenerator.start();
	}

	public static PathPools getInstances() {
		if (sPools == null) {
			sPools = new PathPools();
		}
		return sPools;
	}

	private Thread mPathGenerator = new Thread() {
		@Override
		public void run() {
			PathRequester requester = null;
			Path path = null;

			while (true) {
				requester = mRequesterQueue.poll();
				if (requester != null) {
					mHandlingQueue.add(requester);
					path = AStarSearch.search(requester.mStart,
					        requester.mToTile, requester.mWallList,
					        requester.mObstacleList);

					if (path != null && path.getLength() > 1) {
						requester.mListener.onPathReady(requester.mPathTarget,
						        path);
					}

					mHandlingQueue.remove(requester);
				}
			}

		};
	};

	public void addPathRequester(PathRequester requester) {
		for (PathRequester r : mRequesterQueue) {
			if (requester.mStart.equals(r.mStart)) {
				Log.d(TAG, "requester already in requester queue ..");
				return;
			}
		}
		for (PathRequester handle : mHandlingQueue) {
			if (requester.mStart.equals(handle.mStart)) {
				Log.d(TAG, "requester already in handle queue ..");
				return;
			}
		}
		mRequesterQueue.add(requester);
	}
	
	public void free() {
		mRequesterQueue.clear();
		mHandlingQueue.clear();
		sPools = null;
	}
}
